package com.lagou.search.manager.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lagou.search.dao.EsOrderRepository;
import com.lagou.search.dto.EsOrderQueryDTO;
import com.lagou.search.entity.es.EsOrder;
import com.lagou.search.manager.IEsOrderManager;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Es订单通用服务接口
 * @author yzh
 * @since 2021/12/2
 **/
@Service
public class EsOrderManagerImpl implements IEsOrderManager {

    @Autowired
    private EsOrderRepository esRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private RestHighLevelClient esRestClient;

    @Override
    public List<EsOrder> list() {
        Query query = Query.findAll();
        SearchHits<EsOrder> search = elasticsearchRestTemplate.search(query, EsOrder.class);
        return search.toList().stream().map(SearchHit::getContent).collect(Collectors.toList());
    }

    @Override
    public List<EsOrder> list(EsOrderQueryDTO esOrderQueryDTO) {
        MultiSearchRequest multiSearchRequest = new MultiSearchRequest();
        handleQueryCondition(esOrderQueryDTO, multiSearchRequest);
        MultiSearchResponse multiSearchResponse = null;
        try {
            multiSearchResponse = esRestClient.msearch(multiSearchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        MultiSearchResponse.Item[] responses = multiSearchResponse.getResponses();
        return Arrays.stream(multiSearchResponse.getResponses())
                .map(MultiSearchResponse.Item::getResponse)
                .map(SearchResponse::getHits)
                .filter(searchHits -> searchHits.getHits().length > 0)
                .map(hits -> JSONArray.parseArray(Arrays.toString(hits.getHits()), JSONObject.class))
                .flatMap(Collection::parallelStream)
                .map(v -> v.getObject("_source", EsOrder.class))
                .collect(Collectors.toList());
    }

    /**
     * 处理查询条件
     * @param esOrderQueryDTO es订单查询条件
     * @param multiSearchRequest es多搜索条件
     */
    private void handleQueryCondition(EsOrderQueryDTO esOrderQueryDTO, MultiSearchRequest multiSearchRequest) {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("order");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        if(StringUtils.isNoneBlank(esOrderQueryDTO.getOrderNo())) {
            searchSourceBuilder.query(QueryBuilders.termQuery("orderNo", esOrderQueryDTO.getOrderNo()));
        }
        if(esOrderQueryDTO.getUserId() != null) {
            searchSourceBuilder.query(QueryBuilders.termQuery("userId", esOrderQueryDTO.getUserId()));
        }
        if(searchSourceBuilder.size() <= 0) {
            searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        }
        searchRequest.source(searchSourceBuilder);
        multiSearchRequest.add(searchRequest);
    }

    @Override
    public void saveBatch(List<EsOrder> esOrders) {
        esRepository.saveAll(esOrders);
    }

    @Override
    public void save(EsOrder esOrder) {
        esRepository.save(esOrder);
    }

    @Override
    public void remove(Long id) {
        esRepository.deleteById(id);
    }

}